package util;

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;

import net.ByteBuffer;
import util.loaders.DataLoader;
import util.loaders.ImageLoader;
import util.loaders.SoundLoader;


/**
 * Utility class for controlling the loading and caching of all game
 * resources.
 * 
 * ImageLoader ---> Images
 * SoundLoader ---> Sounds
 * DataLoader  ---> Anything (stats, maps, etc..)
 * 
 * @author Jason
 *
 */
public final class ResourceManager {

	private HashMap<String, Sound> soundCache
		= new HashMap<String, Sound>();
	
	private HashMap<String, BufferedImage> imageCache
		= new HashMap<String, BufferedImage>();
	
	private HashMap<String, byte[]> dataCache
		= new HashMap<String, byte[]>();
	
	private ImageLoader imageLoader;
	private SoundLoader soundLoader;
	private DataLoader dataLoader;
	
	private boolean cache = false;
	
	private final ByteBuffer dataBuffer = new ByteBuffer();
	
	public ResourceManager(ImageLoader imageLoader){
		this.imageLoader = imageLoader;
	}
	
	public ResourceManager(ImageLoader imageLoader, SoundLoader soundLoader){
		this.imageLoader = imageLoader;
		this.soundLoader = soundLoader;
	}
	
	public ResourceManager(ImageLoader imageLoader, SoundLoader soundLoader,
			DataLoader dataLoader){
		this.imageLoader = imageLoader;
		this.soundLoader = soundLoader;
		this.dataLoader = dataLoader;
	}
	
	public BufferedImage getImage(String name){
		return getImage(name, cache);
	}
	
	public BufferedImage getImage(String name, boolean cache){
		BufferedImage image = imageCache.get(name);
		if(image == null){
			try {
				image = imageLoader.load(name);
				if(cache)
					imageCache.put(name, image);
			} catch (IOException e) {
				Logger.log(e);
				return null;
			}
		}
		return image;
	}
	
	public Sound getSound(String name){
		return getSound(name, cache);
	}
	
	public Sound getSound(String name, boolean cache){
		Sound sound = soundCache.get(name);
		if(sound == null){
			try {
				sound = soundLoader.load(name);
				if(cache)
					soundCache.put(name, sound);
			} catch (IOException e) {
				Logger.log(e);
				return null;
			}
		}
		return sound;
	}
	
	public byte[] getData(String name){
		return getData(name, cache);
	}
	
	public byte[] getData(String name, boolean cache){
		byte[] bytes = dataCache.get(name);
		if(bytes == null){
			try {
				InputStream is = dataLoader.load(name);
				synchronized(dataBuffer){
					dataBuffer.reset();
					dataBuffer.read(is);
					bytes = dataBuffer.toByteArray();
				}
				if(cache)
					dataCache.put(name, bytes);
			} catch (IOException e) {
				Logger.log(e);
				return null;
			}
		}
		return bytes;
	}
	
	/**
	 * Sets the default behavior for caching loaded resources.
	 * 
	 * This value is initially False.
	 * 
	 * @param b
	 */
	public void setAutoCache(boolean b){
		this.cache = b;
	}
	
}
